#include "CustomTreeStyle.h"

#include <QDebug>
#include <QStyleOption>
#include <QPainter>
#include <QTreeView>
#include <QStyle>


void CustomTreeStyle::drawPrimitive(PrimitiveElement pe,
                                    const QStyleOption *opt,
                                    QPainter *p,
                                    const QWidget *widget) const
{
    switch (pe) {
    case PE_IndicatorBranch: {
        // 自定义分支线和展开/折叠三角图标
        p->save();
        p->setRenderHint(QPainter::Antialiasing, true);

        const bool isExpandedItem = (opt->state & QStyle::State_Open);
        const bool busDeviceItem = (opt->state & QStyle::State_Children);

        // 绘制总区域
        QRect r = opt->rect;

        // 仅在“当前项自身的分支区域”（最右侧分支块）进行自绘，
        // 避免祖先层级的分支块触发重复绘制
        const QTreeView *view = qobject_cast<const QTreeView *>(widget);
        if (!view && widget) {
            view = qobject_cast<const QTreeView *>(widget->parentWidget());
        }
        if (!view) {
            p->restore();
            return QProxyStyle::drawPrimitive(pe, opt, p, widget);
        }
        // 将坐标转换到 viewport 上，获取当前索引与其视觉矩形
        QPoint vpCenter = (widget == view->viewport())
                          ? opt->rect.center()
                          : view->viewport()->mapFrom(const_cast<QWidget*>(widget), opt->rect.center());
        QModelIndex idx = view->indexAt(vpCenter);
        if (!idx.isValid()) {
            p->restore();
            return QProxyStyle::drawPrimitive(pe, opt, p, widget);
        }
        QRect itemRect = view->visualRect(idx);
        int indent = view->style()->pixelMetric(QStyle::PM_TreeViewIndentation, opt, view);
        QRect expectedBranchRect(itemRect.left() - indent, itemRect.top(), indent, itemRect.height());
        // 允许 2px 容差，过滤掉祖先层级的分支区域调用
        if (qAbs(expectedBranchRect.left() - r.left()) > 2 || qAbs(expectedBranchRect.width() - r.width()) > 2) {
            p->restore();
            return QProxyStyle::drawPrimitive(pe, opt, p, widget);
        }

        // 绘制图标与三角
        QColor arrowColor(90, 90, 90);
        p->setBrush(arrowColor);
        p->setPen(Qt::NoPen);

        QPoint center = r.center();
        QSize sz(15, 15);

        if (busDeviceItem) {
            // 三角位于左侧
            const int triSize = 8;
            const int gap = 3;
            QRect triRect(r.left() + gap, r.center().y() - triSize / 2, triSize, triSize);

            QPolygon tri;
            if (isExpandedItem) {
                // 向下三角形
                tri << QPoint(triRect.left(), triRect.top())
                    << QPoint(triRect.right(), triRect.top())
                    << QPoint(triRect.center().x(), triRect.bottom());
            } else {
                // 向右三角形
                tri << QPoint(triRect.left(), triRect.top())
                    << QPoint(triRect.right(), triRect.center().y())
                    << QPoint(triRect.left(), triRect.bottom());
            }
            p->drawPolygon(tri);

            // 总线图标偏右
            QRect iconRect(center.x(), center.y() - sz.height()/2, sz.width(), sz.height());
            p->drawPixmap(iconRect, QPixmap(":/icons/res/bus-dev.png"));
        } else {
            // 端口图标居中（叶子项不具备 State_Open，始终绘制）
            QRect iconRect(center.x() - sz.width()/2, center.y() - sz.height()/2, sz.width(), sz.height());
            p->drawPixmap(iconRect, QPixmap(":/icons/res/port-dev.png"));
        }

        // 绘制父子连线（端口项根据父子关系绘制）
        if (!busDeviceItem) {
            p->setBrush(Qt::NoBrush);
            p->setPen(QPen(QColor("black"), 1.5));

            QPoint childrenPt(QPoint(r.left(), r.center().y()));
            if (view && idx.isValid()) {
                QModelIndex parent = idx.parent();
                if (parent.isValid()) {
                    QRect itemRect = view->visualRect(parent);
                    int indent = view->style()->pixelMetric(QStyle::PM_TreeViewIndentation, opt, view);
                    QRect branchRect(itemRect);
                    branchRect.translate(-indent, 0);
                    branchRect.moveCenter(QPoint(branchRect.center().x(), itemRect.center().y()));
                    QPoint parentPt(indent - indent / 4, branchRect.bottom());
                    // 构建贝塞尔曲线路径，采用归一化控制点 (0.00, 0.00, 0.00, 1.00)
                    QPointF parentF(parentPt);
                    QPointF childF(childrenPt);
                    QPointF delta = childF - parentF;
                    QPointF ctrl1(parentF.x() + delta.x() * 0.0,
                                  parentF.y() + delta.y() * 0.0);
                    QPointF ctrl2(parentF.x() + delta.x() * 0.0,
                                  parentF.y() + delta.y() * 1.0);
                    QPainterPath path(parentF);
                    path.cubicTo(ctrl1, ctrl2, childF);
                    p->drawPath(path);
                }
            }
        }

        p->restore();
        return; // 不调用基类，完全自绘
    }
    default:
        break;
    }

    // 其他元素使用基类默认绘制
    QProxyStyle::drawPrimitive(pe, opt, p, widget);
}

int CustomTreeStyle::pixelMetric(PixelMetric metric,
                                 const QStyleOption *option,
                                 const QWidget *widget) const
{
    // 扩展分支指示器大小
    switch (metric) {
    // 每深一层，额外偏移 PM_TreeViewIndentation 个像素
    case PM_TreeViewIndentation: {
        return QProxyStyle::pixelMetric(metric, option, widget) + 12;
    }
    default:
        break;
    }
    return QProxyStyle::pixelMetric(metric, option, widget);
}

void CustomItemDelegate::paint(QPainter *p, const QStyleOptionViewItem &opt, const QModelIndex &index) const
{
    p->save();

    // 背景
    if (opt.state & QStyle::State_Selected)
        p->fillRect(opt.rect, QColor("lightgray"));

    // 第三列绘制状态灯
    QRect textRect = opt.rect.adjusted(10, 0, 0, 0);
    if (index.column() == 3 && index.parent().isValid()) {
        const QColor lampColor = getLampColor(ControlPortType(index.data(Qt::UserRole + 1).toInt()));
        const int diameter = qMin(opt.rect.height() - 8, 14);
        const int radius = diameter / 2;
        const int cx = opt.rect.left() + 10 + radius;
        const int cy = opt.rect.center().y() + 2;
        const QRect lampRect(cx - radius, cy - radius, diameter, diameter);

        p->setRenderHint(QPainter::Antialiasing, true);
        p->setPen(Qt::NoPen);
        p->setBrush(lampColor);
        p->drawEllipse(lampRect);

        // 为文字留出图标空间
        textRect = opt.rect.adjusted(10 + diameter + 6, 0, 0, 0);
    }

    // 文字
    QString text = index.data(Qt::DisplayRole).toString();
    p->setPen(Qt::black);
    p->drawText(textRect, Qt::AlignVCenter | Qt::AlignLeft, text);

    p->restore();
}

QSize CustomItemDelegate::sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const
{
    return QSize(100, 20);
}

QColor CustomItemDelegate::getLampColor(ControlPortType type) const
{
    switch (type) {
    case ROUTINE_PORT:
        return QColor("green");
        break;
    case INPUT_PORT:
        return QColor("red");
        break;
    case ENDPOINT_PORT:
        return QColor("yellow");
        break;
    default:
        break;
    }
}
